package org.anachronos.jeep.ui.trace;

import java.text.NumberFormat;
import java.util.HashMap;
import java.util.Map;

import org.anachronos.jeep.model.trace.Invocation;
import org.anachronos.jeep.model.trace.SqlStatementExecution;
import org.anachronos.jeep.model.trace.util.TraceSwitch;
import org.anachronos.jeep.ui.JeepUiPlugin;
import org.anachronos.jeep.ui.trace.util.SqlStatementStyler;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.StyledString.Styler;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.TextStyle;
import org.eclipse.swt.widgets.Display;

public class TraceLabelProvider extends StyledCellLabelProvider {
	private static class FilterStyler extends Styler {
		@Override
		public void applyStyles(final TextStyle textStyle) {
			textStyle.foreground = Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GREEN);
		}
	}

	private class TraceLabelSwitch extends TraceSwitch<StyledString> {
		private final TraceColumnSwitch columnSwitch = new TraceColumnSwitch();

		public void setColumnIndex(final int columnIndex) {
			columnSwitch.setColumnIndex(columnIndex);
		}
		
		@Override
		public StyledString caseSqlStatementExecution(final SqlStatementExecution object) {
			if (columnSwitch.getColumnIndex() == 1) {
				return SqlStatementStyler.getStyledStatement(object);
			} else {
				return super.caseSqlStatementExecution(object);
			}
		}
		
		@Override
		public StyledString caseInvocation(final Invocation object) {
			final Comparable<?> columnElement = columnSwitch.doSwitch(object);
			if (columnElement instanceof String) {
				final String name = (String) columnElement;
				return new StyledString(name);
			} else if (columnElement instanceof Double) {
				final Double percent = (Double) columnElement;
				return new StyledString(NumberFormat.getIntegerInstance().format(percent * 100));
			} else {
				final Number number = (Number) columnElement;
				return new StyledString(NumberFormat.getIntegerInstance().format(number.longValue() / 1000L));
			}
		}
	}
	private final TraceLabelSwitch labelSwitch = new TraceLabelSwitch();
	private final Map<EClass, Image> eClassToIcon = new HashMap<EClass, Image>();
	private final static FilterStyler filterStyler = new FilterStyler();
	private Image filterIcon;
	
	@Override
	public void dispose() {
		super.dispose();
		for(final Image icon : eClassToIcon.values()) {
			icon.dispose();
		}
		if (filterIcon != null) {
			filterIcon.dispose();
		}
	}
	
	@Override
	public void update(final ViewerCell cell) {
		final Object elem = cell.getElement();
		final int columnIndex = cell.getColumnIndex();
		final StyledString styledString;
		if (elem instanceof EObject) {
			final EObject element = (EObject) elem;
			labelSwitch.setColumnIndex(columnIndex);
			styledString = labelSwitch.doSwitch(element);
			if (columnIndex == 0) {
				final Image icon = getIcon(element);
				cell.setImage(icon);
			}
		} else {
			final TraceFilter traceFilter = (TraceFilter) elem;
			final String label = traceFilter.getLabel(columnIndex);
			final Styler styler = traceFilter.isFilterSet(columnIndex) ? filterStyler : StyledString.QUALIFIER_STYLER;
			styledString = new StyledString(label, styler);
			if (columnIndex == 0) {
				if (filterIcon == null) {
					final ImageDescriptor imageDescriptor = JeepUiPlugin.getImageDescriptor("icons/filter.gif");
					filterIcon = imageDescriptor.createImage();
				}
				cell.setImage(filterIcon);
			}
		}
		if (styledString != null) {
			cell.setText(styledString.getString());
			cell.setStyleRanges(styledString.getStyleRanges());
		}
	}
	
	private Image getIcon(final EObject object) {
		final EClass eClass = object.eClass();
		final Image icon;
		if (!eClassToIcon.containsKey(eClass)) {
			final String iconName = "icons/obj16/" + eClass.getName() + ".gif";
			final ImageDescriptor imageDescriptor = JeepUiPlugin.getImageDescriptor(iconName);
			icon = imageDescriptor != null ? imageDescriptor.createImage() : null;
			eClassToIcon.put(eClass, icon);
		} else {
			icon = eClassToIcon.get(eClass);
		}
		return eClassToIcon.put(eClass, icon);
	}
}
